package io.webfolder.cdp.command;

import java.util.List;

import com.google.gson.reflect.TypeToken;

import io.webfolder.cdp.session.SessionInvocationHandler;
import io.webfolder.cdp.type.profiler.Profile;
import io.webfolder.cdp.type.profiler.ScriptCoverage;
import io.webfolder.cdp.type.profiler.ScriptTypeProfile;

public class ProfilerImpl implements Profiler {

	private static final String[] EMPTY_ARGS = new String[] {};
	private static final Object[] EMPTY_VALUES = new Object[] {};
	private static final TypeToken<List<ScriptCoverage>> GET_BEST_EFFORT_COVERAGE = new TypeToken<List<ScriptCoverage>>() {
	};
	private static final TypeToken<List<ScriptCoverage>> TAKE_PRECISE_COVERAGE = new TypeToken<List<ScriptCoverage>>() {
	};
	private static final TypeToken<List<ScriptTypeProfile>> TAKE_TYPE_PROFILE = new TypeToken<List<ScriptTypeProfile>>() {
	};
	private final SessionInvocationHandler handler;

	public ProfilerImpl(SessionInvocationHandler handler) {
		this.handler = handler;
	}

	@Override
	public void disable() {
		handler.invoke("Profiler", "disable", "Profiler.disable", null, void.class, null, true, false, true, EMPTY_ARGS,
				EMPTY_VALUES);
	}

	@Override
	public void enable() {
		handler.invoke("Profiler", "enable", "Profiler.enable", null, void.class, null, true, true, false, EMPTY_ARGS,
				EMPTY_VALUES);
	}

	@Override
	@java.lang.SuppressWarnings("unchecked")
	public List<ScriptCoverage> getBestEffortCoverage() {
		return (List<ScriptCoverage>) handler.invoke("Profiler", "getBestEffortCoverage",
				"Profiler.getBestEffortCoverage", "result", List.class, GET_BEST_EFFORT_COVERAGE.getType(), false,
				false, false, EMPTY_ARGS, EMPTY_VALUES);
	}

	@Override
	public void setSamplingInterval(Integer interval) {
		handler.invoke("Profiler", "setSamplingInterval", "Profiler.setSamplingInterval", null, void.class, null, true,
				false, false, new String[] { "interval" }, new Object[] { interval });
	}

	@Override
	public void start() {
		handler.invoke("Profiler", "start", "Profiler.start", null, void.class, null, true, false, false, EMPTY_ARGS,
				EMPTY_VALUES);
	}

	@Override
	public void startPreciseCoverage() {
		handler.invoke("Profiler", "startPreciseCoverage", "Profiler.startPreciseCoverage", null, void.class, null,
				true, false, false, EMPTY_ARGS, EMPTY_VALUES);
	}

	@Override
	public void startPreciseCoverage(Boolean callCount, Boolean detailed) {
		handler.invoke("Profiler", "startPreciseCoverage", "Profiler.startPreciseCoverage", null, void.class, null,
				true, false, false, new String[] { "callCount", "detailed" }, new Object[] { callCount, detailed });
	}

	@Override
	public void startTypeProfile() {
		handler.invoke("Profiler", "startTypeProfile", "Profiler.startTypeProfile", null, void.class, null, true, false,
				false, EMPTY_ARGS, EMPTY_VALUES);
	}

	@Override
	public Profile stop() {
		return (Profile) handler.invoke("Profiler", "stop", "Profiler.stop", "profile", Profile.class, null, false,
				false, false, EMPTY_ARGS, EMPTY_VALUES);
	}

	@Override
	public void stopPreciseCoverage() {
		handler.invoke("Profiler", "stopPreciseCoverage", "Profiler.stopPreciseCoverage", null, void.class, null, true,
				false, false, EMPTY_ARGS, EMPTY_VALUES);
	}

	@Override
	public void stopTypeProfile() {
		handler.invoke("Profiler", "stopTypeProfile", "Profiler.stopTypeProfile", null, void.class, null, true, false,
				false, EMPTY_ARGS, EMPTY_VALUES);
	}

	@Override
	@java.lang.SuppressWarnings("unchecked")
	public List<ScriptCoverage> takePreciseCoverage() {
		return (List<ScriptCoverage>) handler.invoke("Profiler", "takePreciseCoverage", "Profiler.takePreciseCoverage",
				"result", List.class, TAKE_PRECISE_COVERAGE.getType(), false, false, false, EMPTY_ARGS, EMPTY_VALUES);
	}

	@Override
	@java.lang.SuppressWarnings("unchecked")
	public List<ScriptTypeProfile> takeTypeProfile() {
		return (List<ScriptTypeProfile>) handler.invoke("Profiler", "takeTypeProfile", "Profiler.takeTypeProfile",
				"result", List.class, TAKE_TYPE_PROFILE.getType(), false, false, false, EMPTY_ARGS, EMPTY_VALUES);
	}
}